package com.et.machine.service

import android.app.Service
import android.content.ComponentName
import android.content.Intent
import android.content.ServiceConnection
import android.os.Handler
import android.os.IBinder
import android.os.Looper
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.et.drive.Inlets
import com.et.drive.info.*
import com.et.drive.out.ICashSelectionImpl
import com.et.drive.out.IOutGoodsImpl
import com.et.drive.run.DEFAULT_PORT
import com.et.launch.IPushAidl
import com.et.logger.ELog
import com.et.logger.TAGS
import com.et.machine.BuildConfig
import com.et.machine.broadcast.LaunchBroadcast
import com.et.machine.broadcast.registerPushMessageReceiver
import com.et.machine.broadcast.unRegisterPushMessageReceiver
import com.et.machine.convert.InitParams
import com.et.machine.convert.channelGoodsID
import com.et.machine.convert.channelPrice
import com.et.machine.convert.machineInfo
import com.et.machine.goods.GoodsHelper
import com.et.machine.goods.globalChannelEntityMap
import com.et.machine.push.PushCallBack
import com.et.machine.store.ChannelEntity
import com.et.machine.store.DataBaseUtil
import com.et.machine.util.TcpTask
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

class StableService : Service() {

    private val handler = Handler(Looper.getMainLooper())
    private val coroutineScope = CoroutineScope(Dispatchers.IO)

    private var bindPushService = false
    private var pushService: IPushAidl? = null

    override fun onCreate() {
        super.onCreate()

        registerPushMessageReceiver(applicationContext)
        DataBaseUtil.init(applicationContext)
        GoodsHelper.getInstance().subscribe(applicationContext)
        LaunchBroadcast.register(applicationContext)
        LaunchBroadcast.addCallBack {
            machineInfo?.let {
                Log.d(TAGS.machine, "Sign Info $it")
            }
            binderService()
        }

        ELog.d(TAGS.machine, "machine:stable service onCreate")
        val p = InitParams(DEFAULT_PORT, 19200)
        Inlets.init(p)
        if (BuildConfig.DEBUG) toastTest()

        IMachineSignInfoImpl.observer {
            coroutineScope.launch {
                TcpTask.uploadSignIn(it)
            }
            binderService()
        }

        IChannelInfoImpl.channelInfoSubscribe {
            coroutineScope.launch {
                TcpTask.uploadChannelInfo(it)
            }
            if (it.deviceNumber == 11) {
                for (channel in 1..48) {
                    globalChannelEntityMap[1100 + channel]?.let { it1 ->
                        GoodsHelper.getInstance().update(
                            it1.apply {
                                quantity = if (it.isChannelNormal(channel)) 0x63 else 0
                            }
                        )
                    }
                }
            }
//            globalChannelEntityMap.forEach { entity ->
//                if (it.isChannelNormal(entity.value.channel) != (globalChannelEntityMap[entity.key]?.status == ENABLED)) {
//                    GoodsHelper.getInstance().update(
//                        entity.value.apply {
//                            status = if (it.isChannelNormal(channel)) ENABLED else DISABLED
//                        }
//                    )
//                }
//            }
        }

        ICashSelectionImpl.subscribe {

        }

        IOutGoodsImpl.subscribe {
            ELog.d(TAGS.machine, "out Result $it")
            coroutineScope.launch {
                globalChannelEntityMap[it.device * 1000 + it.channel]?.let { goodsInfo ->
                    TcpTask.uploadOutGoods(
                        it = it,
                        order = "", //TODO 商户号
                        barcode = goodsInfo.barcode
                    )
                }
            }
        }

        ILightTemperatureImpl.subscribe {
            coroutineScope.launch {
                TcpTask.uploadTmp(it)
            }
        }
        IChannelInfoImpl.channelGoodsIdSubscribe { channelGoodsId ->
            coroutineScope.launch {
                channelPrice[channelGoodsId.deviceNumber]?.let { channelPrice ->
                    TcpTask.uploadChannelStatus64(channelGoodsId, channelPrice)
                }
            }

        }

        IChannelInfoImpl.channelPriceSubscribe { channelPrice ->
            coroutineScope.launch {
                channelGoodsID[channelPrice.deviceNumber]?.let { channelGoodsId ->
                    TcpTask.uploadChannelStatus64(channelGoodsId, channelPrice)
                }
//                val box = DataBaseUtil.IChannelDaoBox<IChannelDao>()
//                if (DataBaseUtil.channelDao(box) == NORMAL) {
//                    box.dao?.also { it ->
//                        it.all().subscribe { it1 ->
//                            ELog.d(TAGS.machine, "machine:channel entity size = ${it1.size}")
//                            it1.forEach {
//                                Log.d("================", it.toString())
//                                val price = channelPrice.channelPrices.toBCDInt(it.channel * 2, 2) * 10
//                                if (price != it.priceCent) {
//                                    Log.e("error", "机器与数据库料道金额不匹配 原价格${it.priceCent} 更改后${price}")
//                                    GoodsHelper.getInstance().add(
//                                        it.apply {
//                                            priceCent = price
//                                        }
//                                    )
//
//                                }
//                            }
//                        }
//                    }
//                }
                TcpTask.uploadGoodsInfo(*Array(48) { index ->
                    globalChannelEntityMap[channelPrice.deviceNumber * 1000 + index + 1]
                        ?: ChannelEntity.create(channelPrice.deviceNumber, index + 1)
                })

                //TCP 11
                if (false) {
                    val discountList = MutableList(48) { index ->
                        if (globalChannelEntityMap[channelPrice.deviceNumber * 1000 + index + 1] != null) {
                            return@MutableList globalChannelEntityMap[channelPrice.deviceNumber * 1000 + index + 1]?.discount.toString()
                        } else {
                            return@MutableList "100"
                        }
                    }
                    val barcodeList = MutableList(48) { index ->
                        if (globalChannelEntityMap[channelPrice.deviceNumber * 1000 + index + 1] != null) {
                            return@MutableList globalChannelEntityMap[channelPrice.deviceNumber * 1000 + index + 1]?.barcode.toString()
                        } else {
                            return@MutableList "0238"
                        }
                    }

                    TcpTask.uploadChannelStatus11(
                        channelPrice,
                        discountList,
                        barcodeList
                    )
                }
            }
        }

        IMachineOperationInfoImpl.subscribe {
            coroutineScope.launch {
                TcpTask.uploadOperationInfo(it)
            }

        }

        IMachineIdInfoImpl.observer {
            coroutineScope.launch {
                TcpTask.uploadMachineIDInfo(it)
            }
        }
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        ELog.d(TAGS.machine, "machine:stable service onStartCommand")
        return super.onStartCommand(intent, flags, startId)
    }

    private val serviceConnect = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            ELog.d(TAGS.machine, "machine:push service disconnected")
            bindPushService = true
            pushService = IPushAidl.Stub.asInterface(service ?: return)
            pushService?.subscribe(PushCallBack, "StableService", machineInfo?.uuid)
        }

        override fun onServiceDisconnected(name: ComponentName?) {
            pushService = null
            bindPushService = false
            ELog.d(TAGS.machine, "machine:push service disconnected")
        }
    }

    private fun binderService() {
        if (bindPushService) unbindPushService()
        bindPushService = true
        ELog.d(TAGS.machine, "machine:bind push service")
        Intent().apply {
            setPackage(BuildConfig.APPLICATION_ID)
            type = "${hashCode()}"
            component = ComponentName("com.et.launch", "com.et.launch.push.PushService")
        }.also {
            ELog.d(TAGS.machine, "machine:bind launch pushService")
            applicationContext.bindService(it, serviceConnect, AppCompatActivity.BIND_AUTO_CREATE)
        }
    }

    private fun unbindPushService() {
        applicationContext.unbindService(serviceConnect)
    }

    private fun toastTest() {
        handler.postDelayed({
            Toast.makeText(this, "live", Toast.LENGTH_SHORT).show()
            toastTest()
        }, 10_000)
    }

    override fun onBind(intent: Intent): IBinder? {
        ELog.d(TAGS.machine, "machine:stable service onBind")
        return null
    }

    override fun onDestroy() {
        super.onDestroy()
        unbindPushService()
        unRegisterPushMessageReceiver(applicationContext)
        LaunchBroadcast.unRegister(applicationContext)
        GoodsHelper.getInstance().unsubscribe()
        ELog.d(TAGS.machine, "machine:stable service onDestroy")
    }

}